package com.huey.utils.execl;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.exception.excel.enums.ExcelExportEnum;
import com.huey.utils.exception.ServiceException;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xubo
 * @version 1.0
 * @description 导出工具类
 * @createTime 2019/12/26 10:52
 */
public class ExcelUtils {
    /**
     * 导出（单sheet、多sheet）
     * @param exportDTO 导出配置对象
     * @param response response
     */
    public static void exportExcel(ExportDTO exportDTO, HttpServletResponse response) {
        if (null == exportDTO || StringUtils.isEmpty(exportDTO.getFileName())) {
            throw new ServiceException("文件名不能为空");
        } else if (CollectionUtils.isEmpty(exportDTO.getSheetConfigs())) {
            throw new ServiceException("sheet页配置不能为空");
        } else {
            exportDTO.getSheetConfigs().forEach(config->{
                if (null == config.getClass()) {
                    throw new ServiceException("sheet页配置中cls类型不能为空");
                }
            });
        }

        if (1 == exportDTO.getSheetConfigs().size()) {
            // 单sheet
            SheetConfigDTO sheetConfig = exportDTO.getSheetConfigs().get(0);
            ExportParams exportParams = new ExportParams(null, sheetConfig.getSheetName(), ExcelType.XSSF);
            exportParams.setStyle(ExcelStyleUtil.class);
            exportParams.setI18nHandler(new IExcelI18nHandlerImpl());
            defaultExport(sheetConfig.getDatas(), sheetConfig.getPojoClass(), exportDTO.getFileName(), response, exportParams);
        } else {
            // 多 sheet
            List<Map<String, Object>> list = new ArrayList<>();
            exportDTO.getSheetConfigs().forEach(config->{
                Map<String, Object> sheet = new HashMap<>(3);
                ExportParams exportParams = new ExportParams();
                exportParams.setI18nHandler(new IExcelI18nHandlerImpl());
                exportParams.setSheetName(config.getSheetName());
                // 指定默认样式
                exportParams.setStyle(ExcelStyleUtil.class);
                sheet.put("title", exportParams);
                sheet.put("entity", config.getPojoClass());
                sheet.put("data", config.getDatas());
                list.add(sheet);
            });
            defaultExport(list, exportDTO.getFileName(), response);
        }
    }

    /**
     * 默认的 excel 导出
     *
     * @param list         数据
     * @param pojoClass    pojo类型
     * @param fileName     文件名称
     * @param response
     * @param exportParams 导出参数
     */
    private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) {
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
        downLoadExcel(fileName, response, workbook);
    }

    /**
     * 默认的 excel 导出
     *
     * @param list     数据
     * @param fileName 文件名称
     * @param response
     */
    private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) {
        for (Map<String, Object> map : list) {
            ExportParams exportParams = (ExportParams) map.get("title");
            // xlsx时必须指定XSSF
            exportParams.setType(ExcelType.XSSF);
        }
        Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.XSSF);
        downLoadExcel(fileName, response, workbook);
    }

    /**
     * 下载
     *
     * @param fileName 文件名称
     * @param response
     * @param workbook excel数据
     */
    public static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + "." + ExcelTypeEnum.XLSX.getValue(), "UTF-8"));
            response.flushBuffer();
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            throw new ServiceException(ExcelExportEnum.EXPORT_ERROR.getMsg(), e);
        } finally {
            try {
                IOUtils.closeQuietly(response.getOutputStream());
            } catch (IOException e) {
                throw new ServiceException(ExcelExportEnum.EXPORT_ERROR.getMsg(), e);
            }
            IOUtils.closeQuietly(workbook);
        }
    }

    /**
     * Excel 类型枚举
     */
    enum ExcelTypeEnum {
        /**
         * xls
         */
        XLS("xls"),
        /**
         * xlsx
         */
        XLSX("xlsx");
        private String value;

        ExcelTypeEnum(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}
